package com.test.service.impl;

import com.test.service.PropagationTestService;
import com.test.service.SimplePropagationTestService;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Service
public class PropagationTestServiceImpl implements PropagationTestService {

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private SimplePropagationTestService simplePropagationTestService;

    @Override
    public void noTxCallRequired() {
        jdbcTemplate.execute("INSERT INTO test_table (name) VALUES ('noTxCallRequired PropagationTest')");
        simplePropagationTestService.required();
    }

    @Override
    public void noTxCallRequiredWithException() {
        jdbcTemplate.execute("INSERT INTO test_table (name) VALUES ('noTxCallRequired PropagationTest')");
        simplePropagationTestService.required();
        throw new RuntimeException("noTxCallRequiredWithException PropagationTest");
    }

    @Override
    @Transactional
    public void requiredCallRequired() {
        jdbcTemplate.execute("INSERT INTO test_table (name) VALUES ('noTxCallRequired PropagationTest')");
        simplePropagationTestService.required();
    }

    /**
     * 一个事务
     * 一个连接
     * 两个insert都回滚了
     */
    @Override
    @Transactional
    public void requiredCallRequiredWithException() {
        jdbcTemplate.execute("INSERT INTO test_table (name) VALUES ('requiredCallRequiredWithException PropagationTest')");
        simplePropagationTestService.required();
        throw new RuntimeException("requiredCallRequiredWithException PropagationTest");
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public void querySupports() {
        System.out.println("=====================================querySupports=============================");
        int size = jdbcTemplate.queryForList("select * from test_table").size();
        System.out.println(size + "=====================================querySupports=============================\n\n");
    }

    /**
     * 查询时会多一次commit
     */
    @Override
    @Transactional
    public void queryRequired() {
        System.out.println("=====================================queryRequired=============================");
        int size = jdbcTemplate.queryForList("select * from test_table").size();
        System.out.println(size + "=====================================queryRequired=============================\n\n");
    }

    @Override
    @Transactional
    public void requiredCallNested() {
        System.out.println("PropagationTestServiceImpl @requiredCallNested");
        jdbcTemplate.execute("INSERT INTO test_table (name) VALUES ('requiredCallNested')");
        simplePropagationTestService.nested();
    }


    @Override
    @Transactional
    public void requiredCallNestedWithException() {
        System.out.println("PropagationTestServiceImpl @requiredCallNestedWithException");
        jdbcTemplate.execute("INSERT INTO test_table (name) VALUES ('requiredCallNestedWithException')");
        simplePropagationTestService.nestedWithException();
    }

    /**
     * 嵌套事务回滚可以不影响主事务
     * 回滚方式：Rolling back transaction to savepoint
     */
    @Override
    @Transactional
    public void requiredCallNestedWithCatchException() {
        System.out.println("PropagationTestServiceImpl @requiredCallNestedWithCatchException");
        jdbcTemplate.execute("INSERT INTO test_table (name) VALUES ('requiredCallNestedWithCatchException')");
        try {
            simplePropagationTestService.nestedWithException();
        } catch (final RuntimeException e) {
            System.out.println("catch RuntimeException");
        }
    }

    /**
     * 可以实现部分回滚，
     * 回滚方式和nested不同
     */
    @Override
    public void requiredCallRequiredNewWithCatchException() {
        System.out.println("PropagationTestServiceImpl @requiredCallRequiredNewWithCatchException");
        jdbcTemplate.execute("INSERT INTO test_table (name) VALUES ('requiredCallRequiredNewWithCatchException')");
        try {
            simplePropagationTestService.requiresNewWithException();
        } catch (final RuntimeException e) {
            System.out.println("catch RuntimeException");
        }
    }
}
